home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / dev / c / libiconv_src.lha / src / utf16.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-07  |  2.6 KB  |  90 lines

  1. /*
  2.  * UTF-16
  3.  */
  4.  
  5. /* Specification: RFC 2781 */
  6.  
  7. /* Here we accept FFFE/FEFF marks as endianness indicators everywhere
  8.    in the stream, not just at the beginning. (This is contrary to what
  9.    RFC 2781 section 3.2 specifies, but it allows concatenation of byte
  10.    sequences to work flawlessly, while disagreeing with the RFC behaviour
  11.    only for strings containing U+FEFF characters, which is quite rare.)
  12.    The default is big-endian. */
  13. /* The state is 0 if big-endian, 1 if little-endian. */
  14. static int
  15. utf16_mbtowc (conv_t conv, wchar_t *pwc, const unsigned char *s, int n)
  16. {
  17.   state_t state = conv->istate;
  18.   int count = 0;
  19.   for (; n >= 2;) {
  20.     wchar_t wc = (state ? s[0] + (s[1] << 8) : (s[0] << 8) + s[1]);
  21.     if (wc == 0xfeff) {
  22.     } else if (wc == 0xfffe) {
  23.       state ^= 1;
  24.     } else if (wc >= 0xd800 && wc < 0xdc00) {
  25.       if (n >= 4) {
  26.         wchar_t wc2 = (state ? s[2] + (s[3] << 8) : (s[2] << 8) + s[3]);
  27.         if (!(wc2 >= 0xdc00 && wc2 < 0xe000))
  28.           return RET_ILSEQ;
  29.         *pwc = 0x10000 + ((wc - 0xd800) << 10) + (wc2 - 0xdc00);
  30.         conv->istate = state;
  31.         return count+4;
  32.       } else
  33.         break;
  34.     } else if (wc >= 0xdc00 && wc < 0xe000) {
  35.       return RET_ILSEQ;
  36.     } else {
  37.       *pwc = wc;
  38.       conv->istate = state;
  39.       return count+2;
  40.     }
  41.     s += 2; n -= 2; count += 2;
  42.   }
  43.   conv->istate = state;
  44.   return RET_TOOFEW(count);
  45. }
  46.  
  47. /* We output UTF-16 in big-endian order, with byte-order mark.
  48.    See RFC 2781 section 3.3 for a rationale: Some document formats
  49.    mandate a BOM; the file concatenation issue is not so severe as
  50.    long as the above utf16_mbtowc function is used. */
  51. /* The state is 0 at the beginning, 1 after the BOM has been written. */
  52. static int
  53. utf16_wctomb (conv_t conv, unsigned char *r, wchar_t wc, int n)
  54. {
  55.   if (wc != 0xfffe && !(wc >= 0xd800 && wc < 0xe000)) {
  56.     int count = 0;
  57.     if (!conv->ostate) {
  58.       if (n >= 2) {
  59.         r[0] = 0xFE;
  60.         r[1] = 0xFF;
  61.         r += 2; n -= 2; count += 2;
  62.       } else
  63.         return RET_TOOSMALL;
  64.     }
  65.     if (wc < 0x10000) {
  66.       if (n >= 2) {
  67.         r[0] = (unsigned char) (wc >> 8);
  68.         r[1] = (unsigned char) wc;
  69.         conv->ostate = 1;
  70.         return count+2;
  71.       } else
  72.         return RET_TOOSMALL;
  73.     }
  74.     else if (wc < 0x110000) {
  75.       if (n >= 4) {
  76.         wchar_t wc1 = 0xd800 + ((wc - 0x10000) >> 10);
  77.         wchar_t wc2 = 0xdc00 + ((wc - 0x10000) & 0x3ff);
  78.         r[0] = (unsigned char) (wc1 >> 8);
  79.         r[1] = (unsigned char) wc1;
  80.         r[2] = (unsigned char) (wc2 >> 8);
  81.         r[3] = (unsigned char) wc2;
  82.         conv->ostate = 1;
  83.         return count+4;
  84.       } else
  85.         return RET_TOOSMALL;
  86.     }
  87.   }
  88.   return RET_ILSEQ;
  89. }
  90.